using System;
using System.Data;
using System.Collections.Generic;
using System.Globalization;
using System.Text;

using Kenly.DBFramework.Gateway;

namespace Kenly.DBFramework.Reflection
{
    /// <summary>
    /// Mapping the properties to sql statements .
    /// </summary>
    internal static class AggregateCommandReflector 
    {

        /// <summary>
        /// 
        /// </summary>
        /// <param name="entityType"></param>
        /// <param name="aggregateAttributes"></param>
        /// <param name="groupingAttributes"></param>
        /// <param name="condition"></param>
        /// <param name="order"></param>
        /// <returns></returns>
        public static string GroupSql(Type entityType, List<AggregateAttribute> aggregateAttributes,
            List<GroupingAttribute> groupingAttributes, string condition, Order order)
        {
            ValidateType(entityType);

            if (aggregateAttributes == null || aggregateAttributes.Count <= 0)
            {
                return "";
            }

            if (string.IsNullOrEmpty(condition))
            {
                condition = " null=null ";
            }

            string selectClause = GetSelectClause(aggregateAttributes);
            string selectGroup = GetSelectGroup(groupingAttributes);

            if (!string.IsNullOrEmpty(selectGroup))
            {
                selectClause += "," + selectGroup;
            }

            string sql = string.Concat("SELECT ", selectClause, " FROM ",
               AttributeUtility.ReflectTableName(entityType), " WHERE ", condition);

            string groupBy = GetGroupByClause(groupingAttributes);
            if (!string.IsNullOrEmpty(groupBy))
            {
                sql += " GROUP BY " + groupBy;
            }

            if (order != null && !string.IsNullOrEmpty(order.OrderString))
            {
                sql += " ORDER BY " + order.OrderString;
            }

            return sql;
        }



        private static void ValidateType(Type type)
        {
            if (type == null)
            {
                throw new GatewayException(MsgResource.EmptyEntity);
            }
            if (string.IsNullOrEmpty(AttributeUtility.ReflectTableName(type)))
            {
                throw new GatewayException(MsgResource.InvalidEntityConfig, type);
            }
        }

        private static string GetSelectClause(List<AggregateAttribute> aggregateAttributes)
        {
            StringBuilder clause = new StringBuilder();

            foreach (AggregateAttribute aggregateAttribute in aggregateAttributes)
            {
                if (string.IsNullOrEmpty(aggregateAttribute.ColumnName))
                {
                    continue;
                }

                clause.Append(aggregateAttribute.AggregateType.ToString()+
                    "("+aggregateAttribute.ColumnName+") "+
                    aggregateAttribute.PropertyName+" ,");
            }

            if (clause.Length > 0)
            {
                clause = clause.Remove(clause.Length - 1,1);
            }

            return clause.ToString();
        }

        private static string GetGroupByClause(List<GroupingAttribute> groupingAttributes)
        {
            StringBuilder clause = new StringBuilder();

            foreach (GroupingAttribute groupingAttribute in groupingAttributes)
            {
                if (string.IsNullOrEmpty(groupingAttribute.ColumnName))
                {
                    continue;
                }

                 clause.Append(groupingAttribute.ColumnName + ",");
            }

            if (clause.Length > 0)
            {
                clause = clause.Remove(clause.Length - 1, 1);
            }

            return clause.ToString();
        }

        private static string GetSelectGroup(List<GroupingAttribute> groupingAttributes)
        {
            StringBuilder clause = new StringBuilder();

            foreach (GroupingAttribute groupingAttribute in groupingAttributes)
            {
                if (string.IsNullOrEmpty(groupingAttribute.ColumnName))
                {
                    continue;
                }

                clause.Append(groupingAttribute.ColumnName + " " + groupingAttribute.PropertyName + ",");
            }

            if (clause.Length > 0)
            {
                clause = clause.Remove(clause.Length - 1, 1);
            }

            return clause.ToString();
        }

    }
}
